"""
配置管理器 - 支持插件化和模块化配置
使用单例模式确保配置的一致性，支持动态模块注册
"""

import os
import yaml
from typing import Dict, Any, Optional, Type
from pathlib import Path
from dotenv import load_dotenv
from pydantic import BaseModel
import importlib


class ModuleConfig(BaseModel):
    """模块配置基类"""
    enabled: bool = True
    provider: str
    config: Dict[str, Any] = {}


class SystemConfig(BaseModel):
    """系统配置模型"""
    name: str = "BoLe HR Platform"
    version: str = "0.1.0"
    debug: bool = True
    log_level: str = "INFO"


class ConfigManager:
    """
    配置管理器 - 采用单例模式
    支持：
    1. 插件化模块配置
    2. 环境变量覆盖
    3. 动态配置热重载
    4. 配置验证
    """
    
    _instance = None
    _config: Dict[str, Any] = {}
    _module_registry: Dict[str, Type] = {}
    
    def __new__(cls):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
        return cls._instance
    
    def __init__(self):
        if not hasattr(self, '_initialized'):
            self._initialized = True
            self._load_config()
    
    def _load_config(self):
        """加载配置文件和环境变量"""
        # 加载环境变量
        load_dotenv()
        
        # 加载YAML配置
        config_path = Path(__file__).parent.parent.parent / "config" / "settings.yaml"
        if config_path.exists():
            with open(config_path, 'r', encoding='utf-8') as f:
                self._config = yaml.safe_load(f)
        
        # 环境变量覆盖
        self._apply_env_overrides()
    
    def _apply_env_overrides(self):
        """应用环境变量覆盖"""
        # 替换配置中的环境变量占位符
        self._config = self._replace_env_vars(self._config)
    
    def _replace_env_vars(self, obj):
        """递归替换环境变量"""
        if isinstance(obj, dict):
            return {k: self._replace_env_vars(v) for k, v in obj.items()}
        elif isinstance(obj, list):
            return [self._replace_env_vars(item) for item in obj]
        elif isinstance(obj, str) and obj.startswith("${") and obj.endswith("}"):
            env_var = obj[2:-1]
            return os.getenv(env_var, obj)
        return obj
    
    def get(self, path: str, default: Any = None) -> Any:
        """
        获取配置值，支持点号路径
        例: config.get("data_layer.vector_store.provider")
        """
        keys = path.split('.')
        value = self._config
        
        for key in keys:
            if isinstance(value, dict) and key in value:
                value = value[key]
            else:
                return default
        return value
    
    def get_module_config(self, module_name: str) -> Optional[ModuleConfig]:
        """获取模块配置"""
        config_data = self.get(module_name)
        if config_data:
            return ModuleConfig(**config_data)
        return None
    
    def register_module(self, name: str, module_class: Type):
        """注册模块类 - 支持插件化"""
        self._module_registry[name] = module_class
    
    def get_module_class(self, name: str) -> Optional[Type]:
        """获取已注册的模块类"""
        return self._module_registry.get(name)
    
    def load_module_dynamically(self, class_path: str) -> Type:
        """动态加载模块类"""
        module_path, class_name = class_path.rsplit('.', 1)
        module = importlib.import_module(module_path)
        return getattr(module, class_name)
    
    def reload_config(self):
        """重新加载配置 - 支持热重载"""
        self._load_config()
    
    @property
    def system(self) -> SystemConfig:
        """获取系统配置"""
        system_data = self.get("system", {})
        return SystemConfig(**system_data)


# 全局配置实例
config = ConfigManager()


class ModuleFactory:
    """
    模块工厂 - 实现插件化架构
    根据配置动态创建模块实例
    """
    
    @staticmethod
    def create_module(module_type: str, module_name: str, **kwargs):
        """
        创建模块实例
        
        Args:
            module_type: 模块类型 (如 data_layer, agents)
            module_name: 模块名称 (如 vector_store, resume_analyst)
            **kwargs: 额外参数
        """
        # 获取模块配置
        config_path = f"{module_type}.{module_name}"
        module_config = config.get(config_path)
        
        if not module_config:
            raise ValueError(f"No configuration found for {config_path}")
        
        # 获取类路径
        if 'class' in module_config:
            class_path = module_config['class']
            module_class = config.load_module_dynamically(class_path)
        else:
            # 尝试从注册表获取
            registry_key = f"{module_type}_{module_name}"
            module_class = config.get_module_class(registry_key)
            
        if not module_class:
            raise ValueError(f"No class found for {config_path}")
        
        # 合并配置参数
        init_params = module_config.get('config', {})
        init_params.update(kwargs)
        
        return module_class(**init_params)


# 全局工厂实例
module_factory = ModuleFactory()